#!/usr/bin/env python

"""
processing and combining estout tex tables
"""

import os.path
import string
import pandas as pd

TABLE_DIR = '../tables'
MODEL_DIR = '../../model_nkph'

############################
# splitting up tex tables

def split_tex_table(table_str):
    """split tex table by hlines"""
    table_split1 = table_str.split(r'\hline\hline' + '\n')
    table_split = []
    for ts in table_split1:
        table_split2 = ts.split(r'\hline' + '\n')
        table_split += table_split2
    return table_split

def get_summary_stat_table_info(fname):
    """extract header/body/footer of summary stats table"""
    # read tex file
    fpath = os.path.join(TABLE_DIR, fname + '.tex')
    with open(fpath, 'r') as f:
        table_str = f.read()
    # split
    table_split = split_tex_table(table_str)
    if len(table_split)!=4:
        raise(ValueError('incorrect number of sections for summary table'))
    tab_start, tab_header, tab_body, tab_end = table_split
    return tab_start, tab_header, tab_body, tab_end

def get_regression_table_info(fname):
    """extract header/body/footer of regression table"""
    # read tex file
    fpath = os.path.join(TABLE_DIR, fname + '.tex')
    with open(fpath, 'r') as f:
        table_str = f.read()
    # split
    table_split = split_tex_table(table_str)
    if len(table_split)!=5:
        raise(ValueError('incorrect number of sections for regression table'))
    tab_start, tab_header, tab_body, tab_footer, tab_end = table_split
    return tab_start, tab_header, tab_body, tab_footer, tab_end

def get_bivariate_regression_table_info(fname):
    """extract coeffs/ses/stats from bivariate regression table and reshape"""
    # split table
    tab_start,tab_header,tab_body,tab_footer,tab_end = get_regression_table_info(fname)
    # get column titles
    varnames = tab_header.replace(r'\multicolumn{1}{c}{', '')
    varnames = varnames.replace('}', '')
    varnames = varnames.replace(r'\\' + '\n', '')
    varnames = varnames.split('&')[1:]
    N_vars = len(varnames)
    # get coeffs and SEs
    tab_body = tab_body.replace(r'\\', '').split('\n')
    coeffs = tab_body[0].split('&')[1:]
    ses = tab_body[1].split('&')[1:]
    # get additional statistics
    tab_footer = tab_footer.replace(r'\\', '').split('\n')
    stats_all = []
    stats_names_all = []
    N_stats = len(tab_footer)-1
    for i in range(N_stats):
        stats = tab_footer[i].split('&')
        stats_names_all.append( stats[0] )
        stats_all.append( stats[1:] )
    return varnames, coeffs, ses, stats_all, stats_names_all

############################

def insert_headers_summary_stat_table(fname_output):
    """insert small headers into summary stat table"""
    if fname_output=='t1a_auc_summ_sub_pyedit':
        fname = 't1a_auc_summ_sub'
        ncols = 6
        idx_inserts = [5, 8]
        txt_inserts = ['Bid-to-Cover by type$^\sharp$',
            'Fraction Accepted by type$^\dag$']
    else:
        raise(ValueError('bad table option: %s' % fname_output))

    # split body by lines
    tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
    lines_body = tab_body.split('\n')
    tab_body_out = ''
    for idx in range(len(lines_body)-1):
        if idx in idx_inserts:
            txt_insert = txt_inserts[idx_inserts.index(idx)]
            line_insert = txt_insert + '& '*(ncols-1) + r'\\' + '\n'
        else:
            line_insert = ''
        line_insert += lines_body[idx] + '\n'
        tab_body_out += line_insert 
    # save to tex file
    tab_header_out = tab_start + r'\hline\hline' + '\n'
    tab_header_out += tab_header + r'\hline' + '\n'
    tab_end_out = r'\hline\hline' + '\n' + tab_end
    fpath_output = os.path.join(TABLE_DIR, fname_output + '.tex')
    with open(fpath_output, 'w') as f:
        f.write(tab_header_out + tab_body_out + tab_end_out)
    return


def combine_summary_stat_table(fname_output, ncols=7):
    """combine summary stats tables into panels"""
    # note: assumes header/footer the same for all tables
    
    if fname_output=='t1ab_auc_shock_summary_pyedit':
        # combine auction and shock summary
        combined_table_header = ''
        combined_table_body = ''
        combined_table_end = ''
        
        # panel A: auction summary
        # create panel title
        fname = 't1a_auc_summ'
        panel_title = 'Panel A: Auction Summary Statistics'
        panel_multicol = r'\multicolumn{%d}{l}{\textbf{%s}} \\' % (ncols, panel_title)
        idx_inserts = [5, 8]
        txt_inserts = ['Bid-to-Cover by type$^\sharp$',
            'Fraction Accepted by type$^\dag$']
        # split body by lines
        tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
        combined_table_header = tab_start + r'\hline\hline' + '\n'
        combined_table_header += tab_header + r'\hline' + '\n'
        combined_table_end = r'\hline\hline' + '\n' + tab_end

        # create panel title
        _table_body = r'\\' + '\n'
        _table_body += panel_multicol + '\n'
        lines_body = tab_body.split('\n')
        for idx in range(len(lines_body)-1):
            if idx in idx_inserts:
                txt_insert = txt_inserts[idx_inserts.index(idx)]
                line_insert = txt_insert + '& '*(ncols-1) + r'\\' + '\n'
            else:
                line_insert = ''
            line_insert += lines_body[idx] + '\n'
            _table_body += line_insert 
        combined_table_body += _table_body
        combined_table_body += r'\hline' + '\n'
        
        # panel B: shock summary, all and by term
        panel_title = 'Panel B: Shock Summary Statistics'
        panel_multicol = r'\multicolumn{%d}{l}{\textbf{%s}} \\' % (ncols, panel_title)
        # read table
        fname = 't1b_shock_summary_all'
        tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
        # combine body and panel titles
        _table_body = r'\\' + '\n'
        _table_body += panel_multicol + '\n'
        _table_body += tab_body
        fname = 't1b_shock_summary_terms'
        tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
        _table_body += tab_body
        combined_table_body += _table_body
        combined_table_body += r'\hline' + '\n'
        
        # panel C: shock summary, by zlb/recession
        panel_title = 'Panel C: Shocks Across Regimes'
        panel_multicol = r'\multicolumn{%d}{l}{\textbf{%s}} \\' % (ncols, panel_title)
        # read table
        fname = 't1b_shock_summary_ZLB'
        tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
        # combine body and panel titles
        _table_body = r'\\' + '\n'
        _table_body += panel_multicol + '\n'
        _table_body += tab_body
        fname = 't1b_shock_summary_rec'
        tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
        _table_body += tab_body
        combined_table_body += _table_body
        combined_table_body += r'\hline' + '\n'
        
        # panel D: non-auction shocks
        panel_title = 'Panel D: Non-Auction Shocks'
        panel_multicol = r'\multicolumn{%d}{l}{\textbf{%s}} \\' % (ncols, panel_title)
        # read table
        fname = 't1b_nonauction_summary_terms'
        tab_start, tab_header, tab_body, tab_end = get_summary_stat_table_info(fname)
        # combine body and panel titles
        _table_body = r'\\' + '\n'
        _table_body += panel_multicol + '\n'
        _table_body += tab_body
        combined_table_body += _table_body
        
        # save to tex file
        fpath_output = os.path.join(TABLE_DIR, fname_output + '.tex')
        with open(fpath_output, 'w') as f:
            f.write(combined_table_header + combined_table_body + combined_table_end)
    else:
        raise(ValueError('bad table option: %s' % fname_output))
    return


def _combine_regression_tables(fnames, panel_strs, ncols):
    """combine multiple regression tables into various subpanels"""
    # note: assumes header/footer the same for all tables
    # combine
    N_panels = len(fnames)
    combined_table_header = ''
    combined_table_body = ''
    combined_table_end = ''
    for (i, fname) in enumerate(fnames):
        # create panel title
        panel_title = 'Panel %c: %s' % (string.ascii_uppercase[i], panel_strs[i])
        panel_multicol = r'\multicolumn{%d}{l}{\textbf{%s}} \\' % (ncols, panel_title)
        # read table
        tab_start, tab_header, tab_body, tab_footer, tab_end = \
            get_regression_table_info(fname)
        if i==0:
            combined_table_header = tab_start + r'\hline\hline' + '\n'
            combined_table_header += tab_header + r'\hline' + '\n'
            combined_table_end = r'\hline\hline' + '\n' + tab_end
        # combine body and panel titles
        _table_body = r'\\' + '\n'
        _table_body += panel_multicol + '\n'
        _table_body += tab_body
        _table_body += r'\hline' + '\n'
        _table_body += tab_footer
        combined_table_body += _table_body
        if i<N_panels-1:
            combined_table_body += r'\hline' + '\n'
    return combined_table_header, combined_table_body, combined_table_end



def combine_regression_tables(fname_output):
    """combine auction demand/PH regression tables into subpanels"""
    # different figures/titles for output
    if fname_output=='t1c_auc_demand_combined_pyedit':
        fnames = ['t1c_auc_demand_b2c', 
            't1c_auc_demand_b2c_types',
            't1c_auc_demand_frac_types']
        panel_strs = ['Total Bid-to-Cover Ratio', 
            'Bid-to-Cover by Bidder Type',
            'Fraction Accepted by Bidder Type']
        ncols = 8
    elif fname_output=='t3e_ph_regression_combined_pyedit':
        fnames = ['t3e_ph_regression_misc', 't3e_ph_regression_corp']
        panel_strs = ['Crisis Localization', 'Crisis and Maturity Localization']
        ncols = 7
    else:
        raise(ValueError('bad table option: %s' % fname_output))

    # combine
    combined_table_header, combined_table_body, combined_table_end = \
        _combine_regression_tables(fnames, panel_strs, ncols)
    # save to tex file
    fpath_output = os.path.join(TABLE_DIR, fname_output + '.tex')
    with open(fpath_output, 'w') as f:
        f.write(combined_table_header + combined_table_body + combined_table_end)
    return



def _make_pivot_header(s_titles):
    return r"""{
\def\sym#1{\ifmmode^{#1}\else\(^{#1}\)\fi}
\begin{tabular}{llcccc}
\hline\hline
\multirow{2}{*}{%s} & %s & %s & %s & %s & %s \\
                    \cline{2-6}
                    & (1) & (2) & (3) & (4) & (5) \\                    
\hline
    """ % s_titles

def pivot_bivariate_regression_table_info(varnames, coeffs, ses, stats_all):
    """pivot and combine regression info"""
    # create pivoted info
    N_vars = len(varnames)
    N_stats = len(stats_all)
    N_cols = N_stats + 2
    pivot_txt_all = []
    for i in range(N_vars):
        # combine variable, coeff, and stats into one line
        varname = varnames[i]
        coeff = coeffs[i]
        se = ses[i]
        stats = [stats_all[j][i] for j in range(N_stats)]
        piv_data = [varname, coeff, se]
        for s in stats:
            piv_data.append(s)
        piv_txt = '&'.join(piv_data)
        piv_txt += r'\\' + '\n'
        # combine
        pivot_txt_all.append(piv_txt)
    return pivot_txt_all

def pivot_regression_table(fname_output):
    """combine and pivot regression tables into panels"""
    # read info from multiple bivariate tables
    # create table header and footer
    if fname_output=='t2a_asset_price_combined_pyedit':
        # baseline OLS regressions
        s_titles = ('Asset type','Estimate','Std. Err.','Obs.','$R^{2}$','Sample')
        table_header = _make_pivot_header(s_titles)
        fnames = [
            't2a_asset_price_corpdebt',
            't2a_asset_price_equity',
            't2a_asset_price_infl_comm_spr', 
            't2a_asset_price_ffr',
        ]
        fname_taq = 't2a_asset_price_taq'
        ncols = 6
    elif fname_output=='t2b_iv_asset_price_combined_pyedit':
        # appendix IV OLS regressions
        s_titles = ('Asset type','Estimate','Std. Err.','Obs.','F-stat','Sample')
        table_header = _make_pivot_header(s_titles)
        fnames = [
            't2b_iv_asset_price_corpdebt',
            't2b_iv_asset_price_equity',
            't2b_iv_asset_price_infl_comm_spr',
            't2b_iv_asset_price_ffr',
        ]
        fname_taq = 't2b_iv_asset_price_taq'
        ncols = 6
    else:
        raise(ValueError('bad table option: %s' % fname_output))
    
    table_footer = r"""\hline\hline
    \end{tabular}
    }
    """
    
    # get intraday data, combine with daily by group
    varnames_taq, coeffs_taq, ses_taq, stats_taq, stats_names = \
        get_bivariate_regression_table_info(fname_taq)
    if varnames_taq!=['LQD', 'HYG', 'GLD', 'SPY', 'IWM', 'MBB', 'VMBS']:
        raise(ValueError('input intraday table in wrong order'))
    pivot_txt_taq = pivot_bivariate_regression_table_info(
        varnames_taq, coeffs_taq, ses_taq, stats_taq)
    panel_strs = [
        'Corporate and Private Debt',
        'Equities', 
        'Swaps, Commodities, and Spreads',
        'Federal Funds Futures'
    ]
    # for appending intraday data to daily regression data
    panel_taq_idxs = [ [0,1,5,6], [3,4], [2,], [], [] ]
    
    # combine; also save subsets
    N_panels = len(fnames)
    combined_table_body = ''
    combined_table_body_X = [''] * N_panels
    for i in range(len(fnames)):
        # create panel title
        panel_title = 'Panel %c: %s' % (string.ascii_uppercase[i], panel_strs[i])
        panel_multicol = r'\multicolumn{%d}{l}{\textbf{%s}} \\' % (ncols, panel_title)
        # read table
        fname = fnames[i]
        varnames, coeffs, ses, stats, _ = get_bivariate_regression_table_info(fname)
        pivot_txt = pivot_bivariate_regression_table_info(varnames, coeffs, ses, stats)
        # combine with relevant intraday data
        idx = panel_taq_idxs[i]
        pivot_txt_c = ''
        for j in idx:
            pivot_txt_c += pivot_txt_taq[j]
        for p in pivot_txt:
            pivot_txt_c += p
        
        # combine with panel titles
        _table_body = r'\\' + '\n'
        _table_body += panel_multicol + '\n'
        _table_body += pivot_txt_c
        combined_table_body += _table_body
        combined_table_body_X[i] += _table_body
        if i<N_panels-1:
            combined_table_body += r'\hline' + '\n'
    # save to tex file
    fpath_output = os.path.join(TABLE_DIR, fname_output + '.tex')
    with open(fpath_output, 'w') as f:
        f.write( table_header + combined_table_body + table_footer)
    # save subsets
    for i in range(len(fnames)):
        fname_sub = fname_output + "_" + str(i)
        fpath_output = os.path.join(TABLE_DIR, fname_sub + '.tex')
        with open(fpath_output, 'w') as f:
            f.write( table_header + combined_table_body_X[i] + table_footer)

    return


########################################################################
# model tables
def _param_to_latex(paramname):
    # latex version of parameter names
    if paramname=="s_i":
        paramname_latex = r" \sigma_i "
        param_desc = r"Monetary Policy Vol."
    elif paramname=="s_d":
        paramname_latex = r" \sigma_d "
        param_desc = r"Risky Payoff Vol."
    elif paramname=="s_zpi":
        paramname_latex = r" \sigma_{z,\pi} "
        param_desc = r"Cost-Push Shock Vol."
    elif paramname=="s_zx":
        paramname_latex = r" \sigma_{z,x} "
        param_desc = r"Agg.\ Demand Shock Vol."

    elif paramname=="k_i":
        paramname_latex = r" \kappa_i "
        param_desc = r"Monetary Policy Inertia"
    elif paramname=="k_d":
        paramname_latex = r" \kappa_d "
        param_desc = r"Risky Payoff Inertia"
    elif paramname=="k_zpi":
        paramname_latex = r" \kappa_{z,\pi} "
        param_desc = r"Cost-Push Shock Inertia"
    elif paramname=="k_zx":
        paramname_latex = r" \kappa_{z,x} "
        param_desc = r"Agg.\ Demand Shock Inertia"

    elif paramname=="p_ipi":
        paramname_latex = r" \phi_\pi "
        param_desc = r"Inflation Taylor Coeff."
    elif paramname=="p_ix":
        paramname_latex = r" \phi_x "
        param_desc = r"Output Taylor Coeff."
    elif paramname=="p_dpi":
        paramname_latex = r" \psi_\pi "
        param_desc = r"Risky Payoff Inflation Coeff."
    elif paramname=="p_dx":
        paramname_latex = r" \psi_x "
        param_desc = r"Risky Payoff Output Coeff."
    
    elif paramname=="delta_x":
        paramname_latex = r" \delta "
        param_desc = r"Nominal Rigidity"
    elif paramname=="rho_pi":
        paramname_latex = r" \rho "
        param_desc = r"Discount Factor"
    elif paramname=="siginv":
        paramname_latex = r" \varsigma^{-1} "
        param_desc = r"Intertemporal Elasticity"
    
    elif paramname=="s_b":
        paramname_latex = r" a \cdot \sigma_\beta \cdot \theta_0 "
        param_desc = r"Habitat Demand Size"
    elif paramname=="k_b":
        paramname_latex = r" \kappa_\beta "
        param_desc = r"Habitat Demand Inertia"
    elif paramname=="p_bi":
        paramname_latex = r" a \cdot \phi_{i,\beta} "
        param_desc = r"Habitat Demand Short Rate Response"
    elif paramname=="a0":
        paramname_latex = r" a \cdot \alpha_0 "
        param_desc = r"Habitat Elasticity Size"
    
    elif paramname=="n0":
        paramname_latex = r" \eta_0 "
        param_desc = r"Eff.\ Rate Risky Wgt."
    elif paramname=="eta1_til":
        paramname_latex = r" \eta_1 "
        param_desc = r"Eff.\ Rate Maturity Wgt."

    elif paramname=="alpha1":
        paramname_latex = r" \alpha_1 "
        param_desc = r"Habitat Elasticity Maturity Wgt."
    elif paramname=="alpha1_til":
        paramname_latex = r" \tilde{\alpha}_1 "
        param_desc = r"Habitat Elasticity Maturity Wgt."
    
    elif paramname=="theta1_s":
        paramname_latex = r" \theta_1^s "
        param_desc = r"Short Treasury Factor Maturity Wgt."
    elif paramname=="theta1_l":
        paramname_latex = r" \theta_1^\ell "
        param_desc = r"Long Treasury Factor Maturity Wgt."
    elif paramname=="theta1_til":
        paramname_latex = r" \tilde{\theta}_1 "
        param_desc = r"Risky Factor Maturity Wgt."
    
    else:
        raise(ValueError('bad paramname: %s' % paramname))
    return paramname_latex, param_desc


def _qe_param_to_latex(paramname, qe_type="QE"):
    # QE/QT params to latex
    
    if paramname=="theta1_QE":
        if qe_type=="QE":
            paramname_latex = r" \theta_1^{QE} " 
            param_desc = r"QE1 Maturity Wgt."
        else:
            paramname_latex = r" \theta_1^{QT} " 
            param_desc = r"QT Maturity Wgt."
    elif paramname=="kappa_QE":
        if qe_type=="QE":
            paramname_latex = r" \kappa_{QE} " 
            param_desc = r"QE1 Inertia"
        else:
            paramname_latex = r" \kappa_{QT,A} " 
            param_desc = r"QT Inertia, Active Comp."
    elif paramname=="kappa_QE_p":
        # only QT
        paramname_latex = r" \kappa_{QT,P} " 
        param_desc = r"QT Inertia, Passive Comp."
    elif paramname=="gamma_QE_p":
        # only QT
        paramname_latex = r" \gamma_{QT,A,P} " 
        param_desc = r"QT Passive Comp.\ Response"
            
    else:
        raise(ValueError('bad paramname: %s' % paramname))
    return paramname_latex, param_desc



def _scalar_varname_to_latex(varname):
    # latex version of variable names
    # split difference operator
    if varname[0]=="D":
        is_diff = True
        if varname[:3]=="D1_":
            varname_latex = r" \Delta_s "
            varname = varname[3:]
        elif varname[:4]=="D12_":
            varname_latex = r" \Delta "
            varname = varname[4:]
        else:
            raise(ValueError('bad varname: %s' % varname))
    else:
        is_diff = False
        varname_latex = r""
    
    # variable name
    if varname=="ishort":
        varname_latex += r" y_t^{(1)} "
    elif varname=="ishort_diff":
        if is_diff:
            varname_latex += r" ( \tilde{y}_t^{(1)} - y_t^{(1)} ) "
        else:
            varname_latex += r" \tilde{y}_t^{(1)} - y_t^{(1)} "
    elif varname=="pi":
        varname_latex += r" \pi_t "
    elif varname=="x":
        varname_latex += r" x_t "
    else:
        raise(ValueError('bad varname: %s' % varname))
    return varname_latex


def _scalar_mmts_to_latex(var_i, var_j, cov_type):
    # latex version of targeted scalar moments
    if cov_type=="sd":
        mmt_latex = r" \sigma  ( " 
        is_sd = True
    elif cov_type=="corr":
        mmt_latex = r" \rho  ( " 
        is_sd = False
    else:
        raise(ValueError('bad cov_type: %s' % cov_type))
    # sd/corr variables
    if is_sd:
        var_i_latex = _scalar_varname_to_latex(var_i)
        mmt_latex += var_i_latex
    else:
        var_i_latex = _scalar_varname_to_latex(var_i)
        var_j_latex = _scalar_varname_to_latex(var_j)
        mmt_latex += var_i_latex + r" , " + var_j_latex
    mmt_latex += r" ) "
    return mmt_latex




def _summarize_calibrated_model():
    # latex table of calibrated parameters
    # pull out low and high parameter estimates
    fname_low_params = os.path.join(MODEL_DIR, 'models/baseline_low_mmts.xlsx')
    df_low_params_fit = pd.read_excel(fname_low_params, sheet_name="params_constraints") 
    df_low_params_fix = pd.read_excel(fname_low_params, sheet_name="params_fixed")
    df_low_params = df_low_params_fit.iloc[:, [0, 1]].rename({'init':'val'}, axis=1)
    df_low_params = pd.concat( [ df_low_params, df_low_params_fix.iloc[:, [0, 1]] ] )
    df_low_params.set_index("param", inplace=True)
    
    fname_high_params = os.path.join(MODEL_DIR, 'models/baseline_high_mmts.xlsx')
    df_high_params_fit = pd.read_excel(fname_high_params, sheet_name="params_constraints") 
    df_high_params_fix = pd.read_excel(fname_high_params, sheet_name="params_fixed")
    df_high_params = df_high_params_fit.iloc[:, [0, 1]].rename({'init':'val'}, axis=1)
    df_high_params = pd.concat( [ df_high_params, df_high_params_fix.iloc[:, [0, 1]] ] )
    df_high_params.set_index("param", inplace=True)
    
    tbl_str = r""
    # re-order parameters
    param_order = [
        's_i', 'k_i', 's_d', 'k_d', 's_zpi', 'k_zpi', 's_zx', 'k_zx', 
        'p_ipi', 'p_dx', 'delta_x', 'rho_pi', 'siginv', 
        'k_b', 'a0', 's_b', 'p_bi',
        'theta1_s', 'theta1_l', 'theta1_til', 'alpha1'
    ]
    # whether to use 3 or 2 digit formatting
    param_fmts = [
        1, 1, 1, 1, 1, 1, 1, 1, 
        1, 1, 1, 0, 0,
        1, 1, 1, 1, 
        0, 0, 0, 0,
    ]
    param_crisis = ['a0', 's_b', 'p_bi']
    for param, p_fmt in zip(param_order, param_fmts):
        param_latex, param_desc = _param_to_latex(param)
        val_low = df_low_params.xs(param).val
        if param in param_crisis:
            val_high = df_high_params.xs(param).val
            tbl_line = f" ${param_latex}$ & ${val_low:.3f}$ & $({val_high:.3f})$ & {param_desc} "
        else:
            if p_fmt==0:
                tbl_line = f" ${param_latex}$ & ${val_low:.2f}$ & & {param_desc} "
            else:
                tbl_line = f" ${param_latex}$ & ${val_low:.3f}$ & & {param_desc} "
        # add to table
        tbl_str += tbl_line + r" \\ " + "\n"
    return tbl_str


def _summarize_model_fit():
    # latex table of targeted (scalar) moments
    fname_low_fit = os.path.join(MODEL_DIR, 'output/low_crisis_fit.xlsx')
    df_sc_mmts = pd.read_excel(fname_low_fit, sheet_name="scalar_moments") 
    
    tbl_str = r""    
    # re-order moments
    mmt_idx_order = [0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 8, 9, 10,]
    for idx in mmt_idx_order:
        row = df_sc_mmts.iloc[idx, :]
        # get moment latex str
        mmt_latex = _scalar_mmts_to_latex(row['var_i'], row['var_j'], row['cov_type'])
        # data and model value
        bhat, b = row["bhat"], row["b"]
        tbl_line = f" ${mmt_latex}$ & ${bhat:.3f}$ & & ${b:.3f}$ "
        # add to table
        tbl_str += tbl_line + r" \\ " + "\n"
    return tbl_str


def _summarize_QE_params():
    # latex table of QE/QT parameters
    # pull out QE/QT parameters
    fname_qe_params = os.path.join(MODEL_DIR,
        'models/baseline_high_QE_passive.xlsx')
    df_qe_params = pd.read_excel(fname_qe_params, sheet_name="params_fixed")
    df_qe_params = df_qe_params.iloc[:, [0, 1]]
    df_qe_params.set_index("param", inplace=True)
    fname_qt_params = os.path.join(MODEL_DIR,
        'models/baseline_med_QT_passive.xlsx')
    df_qt_params = pd.read_excel(fname_qt_params, sheet_name="params_fixed")
    df_qt_params = df_qt_params.iloc[:, [0, 1]]
    df_qt_params.set_index("param", inplace=True)
    
    tbl_str = r""    
    # re-order parameters, QE
    param_order = ['theta1_QE', 'kappa_QE']
    for param in param_order:
        param_latex, param_desc = _qe_param_to_latex(param, qe_type="QE")
        val = df_qe_params.xs(param).val
        tbl_line = f" ${param_latex}$ & ${val:.2f}$ & & {param_desc} "
        # add to table
        tbl_str += tbl_line + r" \\ " + "\n"
    
    # re-order parameters, QT
    param_order = ['theta1_QE', 'kappa_QE', 'kappa_QE_p', 'gamma_QE_p']
    for param in param_order:
        param_latex, param_desc = _qe_param_to_latex(param, qe_type="QT")
        val = df_qt_params.xs(param).val
        tbl_line = f" ${param_latex}$ & ${val:.2f}$ & & {param_desc} "
        # add to table
        tbl_str += tbl_line + r" \\ " + "\n"
    return tbl_str


def combine_model_fit_table(fname_output):
    # calibrated parameters, (scalar) moments, and QE/QT params in combined table
    # header
    tbl_str = r"\begin{tabular}{l@{\hskip 0.5in}cc@{\hskip 0.5in}l}" + "\n"
    tbl_str += r"\hline \hline " + "\n"
    
    # panel: scalar moments
    tbl_str += r"\multicolumn{4}{l}{ \textbf{Panel A: Matched Moments} } \\ " + "\n"
    tbl_str += r"Target Moment & Data & &  Model \\ " + "\n"
    tbl_str += r"\hline " + "\n"
    tbl_str += _summarize_model_fit()
    tbl_str += r"\hline " + "\n"
    

    # panel: calibrated params    
    tbl_str += r"\multicolumn{4}{l}{ \textbf{Panel B: Calibrated Parameters} } \\ " + "\n"
    tbl_str += r"Parameter & Value & (Crisis) & Description \\ " + "\n"
    tbl_str += r"\hline " + "\n"
    tbl_str += _summarize_calibrated_model()
    tbl_str += r"\hline " + "\n"

    # panel: qe/qt params
    tbl_str += r"\multicolumn{4}{l}{ \textbf{Panel C: QE/QT Parameters} } \\ " + "\n"
    #tbl_str += r"Parameter & Value & & Description \\ " + "\n"
    #tbl_str += r"\hline " + "\n"
    tbl_str += _summarize_QE_params()
    
    # footer
    tbl_str += r"\hline \hline " + "\n"
    tbl_str += r"\end{tabular}"
    
    # save
    # save to tex file
    fpath_output = os.path.join(TABLE_DIR, fname_output + '.tex')
    with open(fpath_output, 'w') as f:
        f.write( tbl_str )
    return



#################################################################################

def main():
    import sys
    fname_output = sys.argv[1]
    
    # different options
    if fname_output=='t1ab_auc_shock_summary_pyedit':
        combine_summary_stat_table(fname_output, ncols=7)
    elif fname_output=='t1c_auc_demand_combined_pyedit':
        combine_regression_tables(fname_output)
    elif fname_output=='t2a_asset_price_combined_pyedit':
        pivot_regression_table(fname_output)
    elif fname_output=='t2b_iv_asset_price_combined_pyedit':
        pivot_regression_table(fname_output)
    elif fname_output=='t3e_ph_regression_combined_pyedit':
        combine_regression_tables(fname_output)
    elif fname_output=='calibration_moments_pyedit':
        combine_model_fit_table(fname_output)
    else:
        raise(ValueError('bad table option: %s' % fname_output))
    return
    
    

if __name__ == '__main__':
    main()




